package ru.mirent.libs.filter;

import ru.mirent.utils.RegexpMatcher;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * Проверить, проходит ли переданный текст по одному из регулярных выражений и стратегии.
 * Это позволяет фомировать гибкие проверки, когда требуется одни значения исключить, в другие, наоборот включить.
 */
public class MultipleRegexpListFilter implements Function<String, Boolean> {
    /**
     * Ключ - регулярное выражение, значение - стратегия
     */
    private Map<String, StrategyFilter> strategyFilterMap;
    /**
     * Значение по умолчанию для результата проверки.
     */
    private boolean defaultResult;

    /**
     * Создать объект для проверки истинности исходног текста регуля
     * Для соблюдения порядка добавления элементов используется LinkedHashMap
     * @param strategyFilterMap список регулярных выражений и стратегий для проверок
     * @param defaultResult значение по умолчанию для случаяв, когда проверка не пройдена
     */
    public MultipleRegexpListFilter(Map<String, StrategyFilter> strategyFilterMap, boolean defaultResult) {
        if (!(strategyFilterMap instanceof LinkedHashMap)) {
            throw new RuntimeException(String.format("Ожидаемый тип данных 'LinkedHashMap', фактический: %s",
                    strategyFilterMap.getClass().getSimpleName()));
        }
        this.strategyFilterMap = strategyFilterMap;
        this.defaultResult = defaultResult;
    }

    /**
     * См. {@link MultipleRegexpListFilter#MultipleRegexpListFilter(Map, boolean)}
     */
    public MultipleRegexpListFilter(Map<String, StrategyFilter> strategyFilterMap) {
        this(strategyFilterMap, true);
    }

    public void setStrategyFilterMap(Map<String, StrategyFilter> strategyFilterMap) {
        this.strategyFilterMap = strategyFilterMap;
    }

    public void setDefaultResult(boolean defaultResult) {
        this.defaultResult = defaultResult;
    }

    @Override
    public Boolean apply(String text) {
        boolean result;
        for (Map.Entry<String, StrategyFilter> entry: strategyFilterMap.entrySet()) {
            result = new RegexpMatcher().apply(text, entry.getKey()) == entry.getValue().isValue();
            if (StrategyFilter.EXCLUDE.equals(entry.getValue())) {
                if (!result) {
                    return result;
                }
            } else if (StrategyFilter.INCLUDE.equals(entry.getValue())) {
                if (result) {
                    return result;
                }
            }
        }

        return defaultResult;
    }
}
